import React, { Suspense } from 'react'
import * as classnames from 'classnames'
import { compose } from 'redux'
import { connect } from 'react-redux'
import { createStructuredSelector } from 'reselect'

import injectReducer from 'utils/injectReducer'
import injectSaga from 'utils/injectSaga'
import reducer from 'containers/Widget/reducer'
import viewReducer from 'containers/View/reducer'
import dashboardReducer from 'containers/Dashboard/reducer'
import saga from 'containers/Widget/sagas'
import viewSaga from 'containers/View/sagas'
import dashboardSaga from 'containers/Dashboard/sagas'
import formReducer from 'containers/Dashboard/FormReducer'
import { hideNavigator } from 'containers/App/actions'
import { ViewActions } from 'containers/View/actions'
const { loadViews, loadViewsDetail, loadViewData, loadViewDistinctValue } = ViewActions
import { addWidget, editWidget, loadWidgetDetail, clearCurrentWidget, executeComputed } from 'containers/Widget/actions'
import { makeSelectNewWidget, makeSelectCurrentWidget, makeSelectLoading, makeSelectDataLoading, makeSelectDistinctColumnValues, makeSelectColumnValueLoading } from 'containers/Widget/selectors'
import { makeSelectViews, makeSelectFormedViews } from 'containers/View/selectors'
import { promiseDispatcher } from 'utils/reduxPromisation'
import { loadDashboardDetail, addDashboardItems } from '../../../Dashboard/actions'
import DisplayActions from '../../../Display/actions'

import { IViewBase, IFormedViews, IFormedView } from 'containers/View/types'
import OperatingPanel from './OperatingPanel'
import Widget, { IWidgetProps } from '../Widget'
import { IDataRequestParams } from 'app/containers/Dashboard/Grid'
import EditorHeader from 'components/EditorHeader'
import WorkbenchSettingForm from './WorkbenchSettingForm'
import DashboardItemMask, { IDashboardItemMaskProps } from 'containers/Dashboard/components/DashboardItemMask'
import { GRID_ITEM_MARGIN, DEFAULT_SPLITER, DEFAULT_CACHE_EXPIRED } from 'app/globalConstants'
import {
  GRID_COLS
} from 'app/globalConstants'
import { getStyleConfig } from 'containers/Widget/components/util'
// 用于添加组件到display
import { slideSettings, GraphTypes, SecondaryGraphTypes } from 'containers/Display/components/util'

import ChartTypes from '../../config/chart/ChartTypes'
import { FieldSortTypes, fieldGroupedSort } from '../Config/Sort'
import { message, Form, Modal, Button, Row, Col, Input, InputNumber, Select} from 'antd'
import AntdFormType from 'antd/lib/form/Form'
import 'assets/less/resizer.less'
import { IDistinctValueReqeustParams } from 'app/components/Filters/types'
import { IWorkbenchSettings, WorkbenchQueryMode } from './types'

import { widgetDimensionMigrationRecorder, barChartStylesMigrationRecorder } from 'utils/migrationRecorders'
import { resolve } from 'url';

const styles = require('./Workbench.less')
const utilStyles = require('assets/less/util.less')
const FormItem = Form.Item
const Option = Select.Option

// var widgetDataUpdateFormVisible = false;
var polling = false;

interface IDashboardItem {
  id?: number
  x?: number
  y?: number
  width?: number
  height?: number
  widgetId?: number
  dashboardId?: number
  polling?: boolean
  frequency?: number
}

interface IWidget {
  id?: number
  name: string
  description: string
  type: number
  viewId: number
  projectId: number
  config: string
  publish: boolean
}

interface IWorkbenchProps {
  views: IViewBase[]
  formedViews: IFormedViews
  currentWidget: IWidget
  newWidget: IWidget
  loading: boolean
  dataLoading: boolean
  distinctColumnValues: any[]
  columnValueLoading: boolean
  router: any
  params: { pid: string, wid: string }
  onLoadDashboardDetail: (key: number) => any
  onHideNavigator: () => void
  onLoadViews: (projectId: number, resolve?: any) => void
  onLoadViewDetail: (viewId: number, resolve: () => void) => void
  onLoadViewsDetail: (viewIds: number[], resolve: () => void) => void
  onAddDashboardItems: (portalId: number, items: IDashboardItem[], resolve: (items: IDashboardItem[]) => void) => any
  onAddDisplayLayers: (displayId: any, slideId: any, layers: any[]) => void
  onLoadWidgetDetail: (id: number) => void
  onLoadViewData: (
    viewId: number,
    requestParams: IDataRequestParams,
    resolve: (data) => void,
    reject: (error) => void
  ) => void
  onAddWidget: (widget: IWidget, resolve: () => void) => void
  onEditWidget: (widget: IWidget, resolve: () => void) => void
  onLoadViewDistinctValue: (viewId: number, params: Partial<IDistinctValueReqeustParams>) => void
  onClearCurrentWidget: () => void
  onExecuteComputed: (sql: string) => void
}

interface IWorkbenchStates {
  id: number
  name: string
  description: string
  selectedViewId: number
  controls: any[]
  computed: any[]
  autoLoadData: boolean
  cache: boolean
  expired: number
  splitSize: number
  originalWidgetProps: IWidgetProps
  originalComputed: any[]
  widgetProps: IWidgetProps
  settingFormVisible: boolean
  settings: IWorkbenchSettings
}

// 设置组件数据更新的modal内的表单
interface IWidgetDataUpdateForm extends AntdFormType {
  onReset: () => void
}

const SplitPane = React.lazy(() => import('react-split-pane'))

export class Workbench extends React.Component<IWorkbenchProps, IWorkbenchStates> {

  private operatingPanel: OperatingPanel = null
  private defaultSplitSize = 440
  private maxSplitSize = this.defaultSplitSize * 1.5

  constructor (props) {
    super(props)
    const splitSize = +localStorage.getItem('workbenchSplitSize') || this.defaultSplitSize
    this.state = {
      id: 0,
      name: '',
      description: '',
      selectedViewId: null,
      controls: [],
      computed: [],
      originalComputed: [],
      cache: false,
      autoLoadData: true,
      expired: DEFAULT_CACHE_EXPIRED,
      splitSize,
      originalWidgetProps: null,
      widgetProps: {
        data: [],
        pagination: {
          pageNo: 0,
          pageSize: 0,
          totalCount: 0,
          withPaging: false
        },
        cols: [],
        rows: [],
        metrics: [],
        secondaryMetrics: [],
        filters: [],
        chartStyles: getStyleConfig({}),
        selectedChart: ChartTypes.Table,
        orders: [],
        mode: 'pivot',
        model: {},
        onPaginationChange: this.paginationChange
      },
      settingFormVisible: false,
      settings: this.initSettings(),
      widgetDataUpdateFormVisible: false,
      addingWidget: null
    }
  }

  private placeholder = {
    name: '请输入组件名称',
    description: '请输入描述…'
  }

  public componentWillMount () {
    const { params, onLoadViews, onLoadWidgetDetail } = this.props
    onLoadViews(Number(params.pid), () => {
      if (params.wid !== 'add' && !Number.isNaN(Number(params.wid))) {
        onLoadWidgetDetail(Number(params.wid))
      }
    })
  }

  public componentDidMount () {
    this.props.onHideNavigator()
  }

  public componentWillReceiveProps (nextProps: IWorkbenchProps) {
    const { currentWidget } = nextProps
    if (currentWidget && (currentWidget !== this.props.currentWidget)) {
      const { controls, cache, expired, computed, autoLoadData, cols, rows, ...rest } = JSON.parse(currentWidget.config)
      const updatedCols = cols.map((col) => widgetDimensionMigrationRecorder(col))
      const updatedRows = rows.map((row) => widgetDimensionMigrationRecorder(row))
      if (rest.selectedChart === ChartTypes.Bar) {
        rest.chartStyles = barChartStylesMigrationRecorder(rest.chartStyles)
      }
      this.setState({
        id: currentWidget.id,
        name: currentWidget.name,
        description: currentWidget.description,
        controls,
        cache,
        autoLoadData: autoLoadData === undefined ? true : autoLoadData,
        expired,
        selectedViewId: currentWidget.viewId,
        originalWidgetProps: { cols: updatedCols, rows: updatedRows, ...rest },
        widgetProps: { cols: updatedCols, rows: updatedRows, ...rest },
        originalComputed: computed
      })
    }
  }

  public componentWillUnmount () {
    this.props.onClearCurrentWidget()
    sessionStorage.removeItem('currentItems');

    sessionStorage.removeItem('slideParams');
    sessionStorage.removeItem('currentLayers');
    sessionStorage.removeItem('currentDisplay');
    sessionStorage.removeItem('currentSlide');

    sessionStorage.removeItem('addWidgetFromDashboard');
    sessionStorage.removeItem('addWidgetFromDisplay');
  }

  private initSettings = (): IWorkbenchSettings => {
    let workbenchSettings = {
      queryMode: WorkbenchQueryMode.Immediately,
      multiDrag: false
    }
    try {
      const loginUser = JSON.parse(localStorage.getItem('loginUser'))
      const currentUserWorkbenchSetting = JSON.parse(localStorage.getItem(`${loginUser.id}_workbench_settings`))
      if (currentUserWorkbenchSetting) {
        workbenchSettings = currentUserWorkbenchSetting
      }
    } catch (err) {
      throw new Error(err)
    }
    return workbenchSettings
  }

  private changeName = (e) => {
    this.setState({
      name: e.currentTarget.value
    })
  }

  private changeDesc = (e) => {
    this.setState({
      description: e.currentTarget.value
    })
  }

  private viewSelect = (viewId: number) => {
    const { formedViews } = this.props
    const nextState = {
      selectedViewId: viewId,
      controls: [],
      cache: false,
      expired: DEFAULT_CACHE_EXPIRED
    }
    if (formedViews[viewId]) {
      this.setState(nextState)
    } else {
      this.props.onLoadViewDetail(viewId, () => {
        this.setState(nextState)
      })
    }
  }

  private setControls = (controls: any[]) => {
    this.setState({
      controls
    })
  }

  private deleteComputed = (computeField) => {
    const { from } = computeField
    const { params, onEditWidget } = this.props
    const { id, name, description, selectedViewId, controls, cache, autoLoadData, expired, widgetProps, computed, originalWidgetProps, originalComputed } = this.state
    if (from === 'originalComputed') {
      this.setState({
        originalComputed: originalComputed.filter((oc) => oc.id !== computeField.id)
      }, () => {
        const {originalComputed, computed} = this.state
        const widget = {
          name,
          description,
          type: 1,
          viewId: selectedViewId,
          projectId: Number(params.pid),
          config: JSON.stringify({
            ...widgetProps,
            controls,
            computed: originalComputed && originalComputed ? [...computed, ...originalComputed] : [...computed],
            cache,
            autoLoadData,
            expired,
            data: []
          }),
          publish: true
        }
        if (id) {
          onEditWidget({...widget, id}, () => void 0)
        }
      })
    } else if (from === 'computed') {
      this.setState({
        computed: computed.filter((cm) => cm.id !== computeField.id)
      }, () => {
        const {originalComputed, computed} = this.state
        const widget = {
          name,
          description,
          type: 1,
          viewId: selectedViewId,
          projectId: Number(params.pid),
          config: JSON.stringify({
            ...widgetProps,
            controls,
            computed: originalComputed && originalComputed ? [...computed, ...originalComputed] : [...computed],
            cache,
            autoLoadData,
            expired,
            data: []
          }),
          publish: true
        }
        if (id) {
          onEditWidget({...widget, id}, () => void 0)
        }
      })
    }
  }

  private setComputed = (computeField) => {
    const {computed, originalComputed} = this.state
    const {from, sqlExpression} = computeField
    // todo  首先做sql合法校验； sqlExpression
    let isEdit = void 0
    let newComputed = null
    if (from === 'originalComputed') {
      isEdit = originalComputed ? originalComputed.some((cm) => cm.id === computeField.id) : false
      newComputed =  isEdit ? originalComputed.map((cm) => {
        if (cm.id === computeField.id) {
          return computeField
        } else {
          return cm
        }
      }) : originalComputed.concat(computeField)
      this.setState({
        originalComputed: newComputed
      })
    } else if (from === 'computed') {
      isEdit = computed.some((cm) => cm.id === computeField.id)
      newComputed =  isEdit ? computed.map((cm) => {
        if (cm.id === computeField.id) {
          return computeField
        } else {
          return cm
        }
      }) : computed.concat(computeField)
      this.setState({
        computed: newComputed
      })
    } else {
      this.setState({
        computed: computed.concat(computeField)
      })
    }
  }

  private cacheChange = (e) => {
    this.setState({
      cache: e.target.value
    })
  }

  private expiredChange = (value) => {
    this.setState({
      expired: value
    })
  }

  private setWidgetProps = (widgetProps: IWidgetProps) => {
    const { cols, rows } = widgetProps
    const data = [...(widgetProps.data || this.state.widgetProps.data)]
    const customOrders = cols.concat(rows)
      .filter(({ sort }) => sort && sort.sortType === FieldSortTypes.Custom)
      .map(({ name, sort }) => ({ name, list: sort[FieldSortTypes.Custom].sortList }))
    fieldGroupedSort(data, customOrders)
    this.setState({
      widgetProps: {
        ...widgetProps,
        data
      }
    })
  }

  // 设置组件的数据刷新方式的Modal
  private showWidgetDataUpdateForm = () => {
    this.setState({
      widgetDataUpdateFormVisible: true
    })
  }

  private hideWidgetDataUpdateForm = () => {
    this.setState({
      widgetDataUpdateFormVisible: false
    })

  }

  private widgetDataUpdateForm: IWidgetDataUpdateForm = null
  // private refHandles = {
  //   widgetDataUpdateForm: (f) => { this.widgetDataUpdateForm = f }
  // }

  private afterWidgetDataUpdateFormClose = () => {
    this.props.form.resetFields()
  }

  private onPollingSelect = (val) => {
    polling = (val === 'true');
  }

  

  // 添加组件到dashboard或display
  private saveDashboardItem = () => {
    const {onAddWidget } = this.props
    const { addingWidget } = this.state;
    if(addingWidget) {
      onAddWidget(addingWidget, () => {
        message.success('组件保存成功');
        // widgets 这个项目下所有的组件
        const { widgets, newWidget } = this.props
        console.log('saveDash:',newWidget);
        const formdata: any = this.props.form.getFieldsValue()
        const addSignDashboard = sessionStorage.getItem('addWidgetFromDashboard');
        const addSignDisplay = sessionStorage.getItem('addWidgetFromDisplay');
        // 添加组件到dashboard
        if(newWidget&&addSignDashboard) {
          const [pid, portalId, portalName, dashboardId] = addSignDashboard.split(DEFAULT_SPLITER);
          const currentItems = JSON.parse(sessionStorage.getItem('currentItems'));
          console.log(sessionStorage);
          const cols = GRID_COLS.lg
        
  
          const yArr = [...currentItems.map((item) => item.y + item.height), 0]
          const maxY = Math.max(...yArr)
          const secondMaxY = (maxY === 0) ? 0 : Math.max(...yArr.filter((y) => y !== maxY))
          let maxX = 0
          if (maxY) {
            const maxYItems = currentItems.filter((item) => item.y + item.height === maxY)
            maxX = Math.max(...maxYItems.map((item) => item.x + item.width))
  
            // if (maxX + 6 > cols) {
              // maxX = 0
            // }
          }
          const newItem = {
            dashboardId: dashboardId,
            polling: formdata.polling !== 'false',
            frequency: formdata.frequency
          }
  
  
          const positionInfo = {
            width: 6,
            height: 6
          }
  
          const newItems = [newWidget].map((key, index) => {
            const xAxisTemp = index % 2 !== 0 ? 6 : 0
            const yAxisTemp = index % 2 === 0
              ? secondMaxY + 6 * Math.floor(index / 2)
              : maxY + 6 * Math.floor(index / 2)
            let xAxis
            let yAxis
            if (maxX > 0 && maxX <= 6) {
              xAxis = index % 2 === 0 ? 6 : 0
              yAxis = yAxisTemp
            } else if (maxX === 0) {
              xAxis = xAxisTemp
              yAxis = yAxisTemp
            } else if (maxX > 6) {
              xAxis = xAxisTemp
              yAxis = maxY + 6 * Math.floor(index / 2)
            }
            const item = {
              widgetId: newWidget.id,
              x: xAxis,
              y: yAxis,
              ...newItem,
              ...positionInfo
            }
            return item
          })
          // 新组件的数据视图
          const viewIds = [newWidget.viewId];
          if (viewIds.length) {
            this.props.onLoadViewsDetail(viewIds, () => {
              console.log("加载view成功");
            
              this.props.onAddDashboardItems(portalId, newItems, () => {
                this.hideWidgetDataUpdateForm();
  
                if (addSignDashboard) {
                  sessionStorage.removeItem('addWidgetFromDashboard')
                  sessionStorage.setItem('isReload','true');
                  this.props.router.replace(`/project/${pid}/portal/${portalId}/portalName/${portalName}/dashboard/${dashboardId}`)
                }
              })
            })
          } else {         
            this.props.onAddDashboardItems(portalId, newItems, () => {
              this.hideWidgetDataUpdateForm()
              if (addSignDashboard) {
                sessionStorage.removeItem('addWidgetFromDashboard')
                this.props.router.replace(`/project/${pid}/portal/${portalId}/portalName/${portalName}/dashboard/${dashboardId}`)
              }
            })
          }
        }

        // 添加组件到display
        if(newWidget&&addSignDisplay) {
          const layers = [{
            widgetId: newWidget.id,
            name: newWidget.name,
            type: GraphTypes.Chart,
            params: JSON.stringify({
              ...this.getDefaultSetting(GraphTypes.Chart),
              polling: formdata.polling !== 'false',
              frequency: formdata.frequency
            })
          }]
          let viewIds = [newWidget.viewId];
          viewIds = viewIds.filter((viewId, idx) => viewIds.indexOf(viewId) === idx)
           
          const slideParams = JSON.parse(sessionStorage.getItem('slideParams'));
          const currentLayers = JSON.parse(sessionStorage.getItem('currentLayers'));
          const currentDisplay = JSON.parse(sessionStorage.getItem('currentDisplay'));
          const currentSlide = JSON.parse(sessionStorage.getItem('currentSlide'));

          let maxLayerIndex = currentLayers.length === 0 ?
            0 :
            currentLayers.reduce((acc, layer) => Math.max(acc, layer.index), -Infinity)
          layers.forEach((layer) => {
            layer.index = ++maxLayerIndex
            layer.displaySlideId = currentSlide.id
            layer['params'] = JSON.stringify({
              ...JSON.parse(layer['params']),
              width: (slideParams.width - GRID_ITEM_MARGIN * 5) / 4,
              height: (slideParams.height - GRID_ITEM_MARGIN * 5) / 4,
              positionX: GRID_ITEM_MARGIN,
              positionY: GRID_ITEM_MARGIN
            })
          })
          if (viewIds && viewIds.length) {
              this.props.onLoadViewsDetail(viewIds, () => {
                this.props.onAddDisplayLayers(currentDisplay.id, currentSlide.id, layers, ()=>{
                  this.hideWidgetDataUpdateForm();
              
                  sessionStorage.removeItem('addWidgetFromDisplay')
                  const [pid, displayId] = addSignDisplay.split(DEFAULT_SPLITER)
                  this.props.router.replace(`/project/${pid}/display/${displayId}`)
                  
                })
              })
            
          }
          else {
            this.props.onAddDisplayLayers(currentDisplay.id, currentSlide.id, layers)
            sessionStorage.removeItem('addWidgetFromDisplay')
            const [pid, displayId] = addSignDisplay.split(DEFAULT_SPLITER)
            this.props.router.replace(`/project/${pid}/display/${displayId}`)
          }


          // const {
          //   currentDisplay,
          //   currentSlide,
          //   currentLayers,
          //   onAddDisplayLayers,
          //   onLoadViewsDetail
          // } = this.props
          // const { slideParams } = this.state
          // let maxLayerIndex = currentLayers.length === 0 ?
          //   0 :
          //   currentLayers.reduce((acc, layer) => Math.max(acc, layer.index), -Infinity)
          // layers.forEach((layer) => {
          //   layer.index = ++maxLayerIndex
          //   layer.displaySlideId = currentSlide.id
          //   layer['params'] = JSON.stringify({
          //     ...JSON.parse(layer['params']),
          //     width: (slideParams.width - GRID_ITEM_MARGIN * 5) / 4,
          //     height: (slideParams.height - GRID_ITEM_MARGIN * 5) / 4,
          //     positionX: GRID_ITEM_MARGIN,
          //     positionY: GRID_ITEM_MARGIN
          //   })
          // })
          // if (viewIds && viewIds.length) {
          //   const loadViewIds = viewIds.filter((viewId) => !formedViews[viewId])
          //   if (loadViewIds.length) {
          //     onLoadViewsDetail(loadViewIds, () => {
          //       onAddDisplayLayers(currentDisplay.id, currentSlide.id, layers)
          //     })
          //     return
          //   }
          // }
          // onAddDisplayLayers(currentDisplay.id, currentSlide.id, layers)

        }

      })
    }

  }


  // 保存组件
  private saveWidget = () => {
    const { params, onAddWidget, onEditWidget } = this.props
    const { id, name, description, selectedViewId, controls, cache, expired, widgetProps, computed, originalWidgetProps, originalComputed, autoLoadData } = this.state
    if (!name.trim()) {
      message.error('组件名称不能为空')
      return
    }
    if (!selectedViewId) {
      message.error('请选择一个数据视图')
      return
    }
    const widget = {
      name,
      description,
      type: 1,
      viewId: selectedViewId,
      projectId: Number(params.pid),
      config: JSON.stringify({
        ...widgetProps,
        controls,
        computed: originalComputed && originalComputed ? [...computed, ...originalComputed] : [...computed],
        cache,
        expired,
        autoLoadData,
        data: []
      }),
      publish: true
    }
    console.info({
      widget
    })
    if (id) {
      // 编辑页面上的已有组件
      onEditWidget({...widget, id}, () => {
        message.success('修改成功')
        const editSignDashboard = sessionStorage.getItem('editWidgetFromDashboard')
        const editSignDisplay = sessionStorage.getItem('editWidgetFromDisplay')
        if (editSignDashboard) {
          sessionStorage.removeItem('editWidgetFromDashboard')
          const [pid, portalId, portalName, dashboardId, itemId] = editSignDashboard.split(DEFAULT_SPLITER)
          this.props.router.replace(`/project/${pid}/portal/${portalId}/portalName/${portalName}/dashboard/${dashboardId}`)
        } else if (editSignDisplay) {
          sessionStorage.removeItem('editWidgetFromDisplay')
          const [pid, displayId] = editSignDisplay.split(DEFAULT_SPLITER)
          this.props.router.replace(`/project/${pid}/display/${displayId}`)
        } else {
          this.props.router.replace(`/project/${params.pid}/widgets`)
        }
      })
    } else {
      // 绑定新组件到页面上
      // 弹出窗口，设置数据刷新方式
        this.showWidgetDataUpdateForm();
        this.setState({
          addingWidget: widget
        })
    }
  }

  private getDefaultSetting = (graphType: GraphTypes, secondaryGraphType?: SecondaryGraphTypes) => {
    const type = secondaryGraphType || graphType
    const setting = slideSettings[type]
    if (!setting) {
      return {}
    }
    const defaultSetting = {}
    setting.params.forEach((param) => {
      param.items.forEach((item) => {
        defaultSetting[item.name] = item.default || null
      })
    })
    return defaultSetting
  }

  private cancel = () => {
    sessionStorage.removeItem('editWidgetFromDashboard')
    sessionStorage.removeItem('editWidgetFromDisplay')
    this.props.router.goBack()
  }

  private paginationChange = (pageNo: number, pageSize: number, orders) => {
    this.operatingPanel.flipPage(pageNo, pageSize, orders)
  }

  private chartStylesChange = (propPath: string[], value: string) => {
    const { widgetProps } = this.state
    const { chartStyles } = widgetProps
    const updatedChartStyles = { ...chartStyles }
    propPath.reduce((subObj, propName, idx) => {
      if (idx === propPath.length - 1) {
        subObj[propName] = value
      }
      return subObj[propName]
    }, updatedChartStyles)
    this.setWidgetProps({
      ...widgetProps,
      chartStyles: updatedChartStyles
    })
  }

  private saveSplitSize (newSize: number) {
    localStorage.setItem('workbenchSplitSize', newSize.toString())
  }

  private resizeChart = () => {
    this.setState({
      widgetProps: {
        ...this.state.widgetProps,
        renderType: 'resize'
      }
    })
  }


  private changeAutoLoadData = (e) => {
    this.setState({
      autoLoadData: e.target.value
    })
  }

  private openSettingForm = () => {
    this.setState({
      settingFormVisible: true
    })
  }

  private saveSettingForm = (values: IWorkbenchSettings) => {
    try {
      const loginUser = JSON.parse(localStorage.getItem('loginUser'))
      localStorage.setItem(`${loginUser.id}_workbench_settings`, JSON.stringify(values))
      this.setState({
        settings: values
      })
    } catch (err) {
      throw new Error(err)
    }
    this.closeSettingForm()
  }

  private closeSettingForm = () => {
    this.setState({
      settingFormVisible: false
    })
  }

  public render () {

    const {
      views,
      formedViews,
      loading,
      dataLoading,
      distinctColumnValues,
      columnValueLoading,
      onLoadViewData,
      onLoadViewDistinctValue,
      form,
    } = this.props
    const {
      name,
      description,
      selectedViewId,
      controls,
      cache,
      autoLoadData,
      expired,
      computed,
      splitSize,
      originalWidgetProps,
      originalComputed,
      widgetProps,
      settingFormVisible,
      settings
    } = this.state
    const selectedView = formedViews[selectedViewId]
    const { queryMode, multiDrag } = settings

    const { selectedChart, cols, rows, metrics, data } = widgetProps
    const hasDataConfig = !!(cols.length || rows.length || metrics.length)
    const maskProps: IDashboardItemMaskProps = {
      loading: dataLoading,
      chartType: selectedChart,
      empty: !data.length,
      hasDataConfig
    }

    const { getFieldDecorator } = form

    // saveDashboardItem,将组件与当前仪表板绑定
    const saveDashboardItemButton = (
      <Button
        key="submit"
        size="large"
        type="primary"
        onClick={this.saveDashboardItem}
      >
        保 存
      </Button>
    )

    const frequencyClass = classnames({
      [utilStyles.hide]: !polling
    })

    return (
      <div className={styles.workbench}>
        <EditorHeader
          currentType="workbench"
          className={styles.header}
          name={name}
          description={description}
          placeholder={this.placeholder}
          onNameChange={this.changeName}
          onDescriptionChange={this.changeDesc}
          onSave={this.saveWidget}
          onCancel={this.cancel}
          onSetting={this.openSettingForm}
          loading={loading}
        />
        <div className={styles.body}>
          <Suspense fallback={null}>
            <SplitPane
              split="vertical"
              defaultSize={splitSize}
              minSize={this.defaultSplitSize}
              maxSize={this.maxSplitSize}
              onChange={this.saveSplitSize}
              onDragFinished={this.resizeChart}
            >
              <OperatingPanel
                ref={(f) => this.operatingPanel = f}
                views={views}
                originalWidgetProps={originalWidgetProps}
                originalComputed={originalComputed}
                selectedView={selectedView}
                distinctColumnValues={distinctColumnValues}
                columnValueLoading={columnValueLoading}
                controls={controls}
                cache={cache}
                autoLoadData={autoLoadData}
                expired={expired}
                queryMode={queryMode}
                multiDrag={multiDrag}
                computed={computed}
                onViewSelect={this.viewSelect}
                onChangeAutoLoadData={this.changeAutoLoadData}
                onSetControls={this.setControls}
                onCacheChange={this.cacheChange}
                onExpiredChange={this.expiredChange}
                onSetWidgetProps={this.setWidgetProps}
                onSetComputed={this.setComputed}
                onDeleteComputed={this.deleteComputed}
                onLoadData={onLoadViewData}
                onLoadDistinctValue={onLoadViewDistinctValue}
              />
              <div className={styles.viewPanel}>
                <div className={styles.widgetBlock}>
                  <Widget
                    {...widgetProps}
                    loading={<DashboardItemMask.Loading {...maskProps}/>}
                    empty={<DashboardItemMask.Empty {...maskProps}/>}
                    editing={true}
                    onPaginationChange={this.paginationChange}
                    onChartStylesChange={this.chartStylesChange}
                  />
                </div>
              </div>
            </SplitPane>
          </Suspense>
          <WorkbenchSettingForm
            visible={settingFormVisible}
            settings={settings}
            onSave={this.saveSettingForm}
            onClose={this.closeSettingForm}
          />
          {/* 设置数据刷新方式的modal */}
          <Modal
            title="设置数据刷新方式"
            wrapClassName="ant-modal-large"
            visible={this.state.widgetDataUpdateFormVisible}
            footer={saveDashboardItemButton}
            onCancel={this.hideWidgetDataUpdateForm}
            afterClose={this.afterWidgetDataUpdateFormClose}
          >
            <Form>
              <Row>
                <Col sm={8}>
                  <FormItem
                    label="数据刷新模式"
                    labelCol={{span: 10}}
                    wrapperCol={{span: 14}}
                  >
                    {getFieldDecorator('polling', {
                      initialValue: polling ? 'true' : 'false'
                    })(
                      <Select onSelect={this.onPollingSelect}>
                        <Option value="false">手动刷新</Option>
                        <Option value="true">定时刷新</Option>
                      </Select>
                    )}
                  </FormItem>
                </Col>
                <Col sm={4} className={frequencyClass}>
                  <FormItem
                    label="时长"
                    labelCol={{span: 12}}
                    wrapperCol={{span: 12}}
                  >
                    {getFieldDecorator('frequency', {
                      rules: [{
                        required: true,
                        message: '不能为空'
                      }],
                      initialValue: 60
                    })(
                      <InputNumber min={1} placeholder="秒" />
                    )}
                  </FormItem>
                </Col>
              </Row>
            </Form>
          </Modal>
        </div>
      </div>
    )
  }
}

const mapStateToProps = createStructuredSelector({
  views: makeSelectViews(),
  formedViews: makeSelectFormedViews(),
  currentWidget: makeSelectCurrentWidget(),
  loading: makeSelectLoading(),
  dataLoading: makeSelectDataLoading(),
  distinctColumnValues: makeSelectDistinctColumnValues(),
  columnValueLoading: makeSelectColumnValueLoading(),

  //添加组件到当前dashboard需要的值
  newWidget: makeSelectNewWidget(),

})

export function mapDispatchToProps (dispatch) {
  return {
    onHideNavigator: () => dispatch(hideNavigator()),
    onLoadViews: (projectId, resolve) => dispatch(loadViews(projectId, resolve)),
    onLoadViewDetail: (viewId, resolve) => dispatch(loadViewsDetail([viewId], resolve)),
    onLoadViewsDetail: (viewIds, resolve) => dispatch(loadViewsDetail(viewIds, resolve)),
    onAddDashboardItems: (portalId, items, resolve) => dispatch(addDashboardItems(portalId, items, resolve)),
    onAddDisplayLayers: (displayId, slideId, layers, resolve) => dispatch(DisplayActions.addDisplayLayers(displayId, slideId, layers, resolve)),
    onLoadWidgetDetail: (id) => dispatch(loadWidgetDetail(id)),
    onLoadViewData: (viewId, requestParams, resolve, reject) => dispatch(loadViewData(viewId, requestParams, resolve, reject)),
    onAddWidget: (widget, resolve) => dispatch(addWidget(widget, resolve)),
    onEditWidget: (widget, resolve) => dispatch(editWidget(widget, resolve)),
    onLoadViewDistinctValue: (viewId, params) => dispatch(loadViewDistinctValue(viewId, params)),
    onClearCurrentWidget: () => dispatch(clearCurrentWidget()),
    onExecuteComputed: (sql) => dispatch(executeComputed(sql)),

    onLoadDashboardDetail: (id) => promiseDispatcher(dispatch, loadDashboardDetail, id),
  }
}

const withConnect = connect<{}, {}, IWorkbenchProps>(mapStateToProps, mapDispatchToProps)

const withReducerWidget = injectReducer({ key: 'widget', reducer })
const withSagaWidget = injectSaga({ key: 'widget', saga })

const withReducerView = injectReducer({ key: 'view', reducer: viewReducer })
const withSagaView = injectSaga({ key: 'view', saga: viewSaga })

const withFormReducer = injectReducer({ key: 'form', reducer: formReducer })

const withReducerDashboard = injectReducer({ key: 'dashboard', reducer: dashboardReducer })
const withSagaDashboard = injectSaga({ key: 'dashboard', saga: dashboardSaga })

export default Form.create()(compose(
  withReducerWidget,
  withReducerView,
  withReducerDashboard,
  withFormReducer,
  withSagaView,
  withSagaWidget,
  withSagaDashboard,
  withConnect
)(Workbench))
